package ec.cd.client.profiler;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutionException;

import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;
import ec.cd.common.Networking.Message;
import ec.cd.common.Networking.MessageType;
import ec.cd.common.Sensors;
import ec.cd.common.Sensors.SensorData;

public class Client {
	private static String TAG = "Networking.Client";
	private Socket socket;
	private ObjectOutputStream objOutputStream;
	private TextView loggerTextView;
	private SensorsManager sensorsManager;
	// private ConnectionEventListener connectionEventListener;
	private AsyncTask<Void, String, Boolean> handleConnectionTask;
	private boolean continueDataTransfer;
	private float timesPerSec;

	public static interface ConnectionEventListener {
		public void disconnected();
	}

	public Client(TextView logger, SensorsManager sm, float timesPerSecond) {
		loggerTextView = logger;
		sensorsManager = sm;
		continueDataTransfer = false;
		this.timesPerSec = timesPerSecond;
	}

	// Return true on success, false otherwise
	public boolean connect(String host, int port) {

		try {
			socket = new Socket(host, port);
			objOutputStream = new ObjectOutputStream(socket.getOutputStream());

			return true;
		} catch (UnknownHostException e) {
			Log.e(TAG, e.toString());
		} catch (IOException e) {
			Log.e(TAG, e.toString());
		}

		socket = null;

		return false;
	}

	public boolean connected() {
		return socket != null;
	}

	public void disconnect() {

		continueDataTransfer = false;
		handleConnectionTask.cancel(true);
//		try {
//			handleConnectionTask.get(); // Wait for completion
//		} catch (InterruptedException e) {
//			Log.e(TAG, e.toString());
//		} catch (ExecutionException e) {
//			Log.e(TAG, e.toString());
//		}
//		handleConnectionTask = null;

	}

	public void handleConnection() {
		continueDataTransfer = true;
		handleConnectionTask = new HandleConnectionTask();
		handleConnectionTask.execute((Void) null);
	}

	private class HandleConnectionTask extends AsyncTask<Void, String, Boolean> {
		protected Boolean doInBackground(Void... bls) {
			try {
				// ClientHello
				Message outgoing = new Message();
				SensorData[] sensors_data = new SensorData[2];
				sensors_data[0] = new SensorData();
				sensors_data[0].sensorType = Sensors.ST_ACCELEROMETER;
				sensors_data[0].timestamp = System.currentTimeMillis();
				sensors_data[0].values = new float[] { 1, 2, 3 };
				sensors_data[1] = new SensorData();
				sensors_data[1].sensorType = Sensors.ST_GYROSCOPE;
				sensors_data[1].timestamp = System.currentTimeMillis();
				sensors_data[1].values = new float[] { 1, 2, 3 };
				outgoing.mt = MessageType.ClientSendData;
				outgoing.payload = sensors_data;
				while (continueDataTransfer == true) {
					try {
						Thread.sleep(Math.round(1000 / timesPerSec));
					} catch (Exception ex) {
						Log.e(this.getClass().toString(), "Thread cannot sleep.");
					}
					objOutputStream.writeObject(outgoing);
					// loggerTextView.append("Message Sent");

				}
			} catch (IOException e) {
				Log.e(TAG, e.toString());
			}
			return false;
		}

		protected void onProgressUpdate(String... msgs) {

		}

		protected void onPostExecute(Boolean res) {
			try {
				socket.close();
			} catch (IOException e) {
				Log.e(TAG, e.toString());
			}
			socket = null;
		}
	}
}
